using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Reflection;


namespace RLFtrClc
{
	/// <summary>
	/// The XmlSerializer always checks the State of 
	/// an XmlTextWriter. If the XmlTextWriter did not
	/// write a document declaration the XmlSerializer 
	/// will write one.  
	/// This XmlTextWriter can put the XmlTextWriter
	/// in the correct state to skip the Xml document 
	/// declaration when serializing objects
	/// with the XmlSerializer.
	/// 
	/// To make the XmlSerializer omit the document declaration
	/// simply pass in true for the writeDeclaration parameter
	/// to the constructor:
	/// 
	/// 
	/// </summary>
	public class XmlFragmentWriter : System.Xml.XmlTextWriter
	{
		/// <summary>
		/// 
		/// </summary>
		/// <param name="w"></param>
		/// <param name="writeDeclaration"></param>
		public XmlFragmentWriter( TextWriter w, bool writeDeclaration ) : base( w )
		{
			SetWriteDeclaration( writeDeclaration );
		}
		
		/// <summary>
		/// 
		/// </summary>
		/// <param name="w"></param>
		/// <param name="enc"></param>
		/// <param name="writeDeclaration"></param>
		public XmlFragmentWriter( Stream w, Encoding enc, bool writeDeclaration ) :
			base( w, enc )
		{
			SetWriteDeclaration( writeDeclaration );
		}
		
		/// <summary>
		/// 
		/// </summary>
		/// <param name="filename"></param>
		/// <param name="enc"></param>
		/// <param name="writeDeclaration"></param>
		public XmlFragmentWriter( string filename, Encoding enc, bool writeDeclaration )
			: base( filename, enc )
		{
			SetWriteDeclaration( writeDeclaration );
		}
		private void SetWriteDeclaration( bool doWrite )
		{
			if( false == doWrite )
			{
				SetCurrentStateField();
			}
		}
		private void SetCurrentStateField( )
		{
			// get to the currentState field
			Type xmlTextWriterType = typeof( System.Xml.XmlTextWriter );
			FieldInfo currentStateFieldInfo = xmlTextWriterType.GetField(
				"currentState", BindingFlags.Instance | BindingFlags.NonPublic );

			// get the State enumeration
			Type stateEnumType = xmlTextWriterType.GetNestedType( "State",
				BindingFlags.NonPublic );

			// set the currentState to Prolog written
			currentStateFieldInfo.SetValue( this,
				stateEnumType.GetField( "Prolog" ).GetValue( this ) );

			// Set the stateTable to the correct state for document
			FieldInfo stateTableFieldInfo = xmlTextWriterType.GetField( "stateTable",
				BindingFlags.Instance | BindingFlags.NonPublic );
			FieldInfo stateTableDocumentInfo = xmlTextWriterType.GetField(
				"stateTableDocument", BindingFlags.Instance | BindingFlags.Static |
				BindingFlags.NonPublic );
			stateTableFieldInfo.SetValue( this,
				stateTableDocumentInfo.GetValue( this ) );
		}
	}

}
